package com.hp.gxw.controller;


import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.hp.gxw.cache.BaseCache;
import com.hp.gxw.constant.CacheEnum;
import com.hp.gxw.constant.CountEnum;
import com.hp.gxw.constant.R;
import com.hp.gxw.entity.*;
import com.hp.gxw.service.*;
import com.hp.gxw.utils.ShiroUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.CountDownLatch;
import java.util.function.Consumer;
import java.util.stream.Collectors;

/**
 * <p>
 *  前端控制器
 * </p>
 *
 * @author huangping
 * @since 2024-02-21
 */
@Controller
@RequestMapping("/manage/cost_count")
@Slf4j
public class CostCountController {

    @Autowired
    private BaseCache baseCache;

    @Autowired
    private ISysUserService iSysUserService;

    @Autowired
    private ICostEquipmentDepreciationService iCostEquipmentDepreciationService;

    @Autowired
    private ICostEquipmentUsagerateService iCostEquipmentUsagerateService;

    @Autowired
    private ICostElementsPriceService iCostElementsPriceService;

    @Autowired
    private ICostEquipmentLeaseService iCostEquipmentLeaseService;

    @Autowired
    private ICostCountService iCostCountService;

    @Autowired
    private ICostCountTempService iCostCountTempService;

    @Autowired
    private ICostElementsService iCostElementsService;

    @Autowired
    private ICostCountEquipmentDepreciationLeaseService iCostCountEquipmentDepreciationLeaseService;

//    ExecutorService threadService = Executors.newFixedThreadPool(6);
    R direct_labor = null,equipment_power = null,equipment_depreciation = null,equipment_lease = null,indirect_equipment = null,
        indirect_workhours = null,indirect_manager = null;
    String month = null;

    CountDownLatch latch = new CountDownLatch(7);

    @RequestMapping("/index")
    public String index(){
        return "cost_count/index";
    }

    @RequestMapping("/count_before")
    @ResponseBody
    public R count_before(@RequestBody String count_month){
        month = count_month;
        try {
            //1、检查现在是否在计算中,如果没有则占用
            Object o = baseCache.get(CacheEnum.cost_count.getCode());
            if(o != null){
                Map map = JSON.parseObject(JSON.toJSONString(o), Map.class);
                SysUser user = iSysUserService.getById(map.get("user").toString());
                return R.error("当前有用户:"+user.getUserName()+"正在计算"+map.get("month")+"的数据，请等待计算完后再操作");
            }else{
                Map<String, Object> map = new HashMap<>();
                map.put("user", ShiroUtil.getUserId());
                map.put("month", month);
                baseCache.add(CacheEnum.cost_count.getCode(),map);
            }
            //2、检查计算月数据是否维护进系统
            StringBuffer sb = new StringBuffer();
            //设备折旧
            long count = iCostEquipmentDepreciationService.count(new LambdaQueryWrapper<CostEquipmentDepreciation>().eq(CostEquipmentDepreciation::getHappenMonth, month));
            if(count < 1){
                sb.append("设备折旧本月未维护数据，请前往【菜单】成本模块->成本计算数据->设备折旧，维护数据<br/>");
            }
            //设备租赁
            count = iCostEquipmentLeaseService.count(new LambdaQueryWrapper<CostEquipmentLease>().eq(CostEquipmentLease::getHappenMonth, month));
            if(count < 1){
                sb.append("设备租赁本月未维护数据，请前往【菜单】成本模块->成本计算数据->设备租赁，维护数据<br/>");
            }
            //成本要素金额
            count = iCostElementsPriceService.count(new LambdaQueryWrapper<CostElementsPrice>()
                    .eq(CostElementsPrice::getHappenMonth, month)
                    .gt(CostElementsPrice::getAmount, 0));
            if(count < 1){
                sb.append("成本要素金额本月未维护数据，请前往【菜单】成本模块->成本计算数据->成本要素金额，维护数据<br/>");
            }
            //设备使用率
            count = iCostEquipmentUsagerateService.count(new LambdaQueryWrapper<CostEquipmentUsagerate>().eq(CostEquipmentUsagerate::getHappenMonth, month));
            if(count < 1){
                sb.append("设备使用率本月未维护数据，请前往【菜单】成本模块->成本计算数据->设备使用率，维护数据<br/>");
            }
            //3、生成生产数据并检查是否有问题
            iCostCountService.generateCountData(month);
            //检查工序档案数据完整性
            List<CostCountTemp> processCheckList = iCostCountTempService.list(new LambdaQueryWrapper<CostCountTemp>()
                    .select(CostCountTemp::getProcessCode,CostCountTemp::getProcessName)
                    .isNull(CostCountTemp::getManagerScale).or().isNull(CostCountTemp::getTeamType)
                    .groupBy(CostCountTemp::getProcessCode,CostCountTemp::getProcessName));
            if(processCheckList.size() > 0){
                for (CostCountTemp costCountTemp : processCheckList) {
                    sb.append("工序："+costCountTemp.getProcessCode()+(costCountTemp.getProcessName()==null?"在工序档案中不存在，请联系MES同步工序档案。<br/>":"没设置管理属性占比或者工艺属性类别，请前往【菜单】成本模块->生产工序档案，维护数据<br/>"));
                }
            }
            //检查设备档案数据完整性
            Consumer<LambdaQueryWrapper<CostCountTemp>> lambdaQueryWrapperConsumer = wrapper -> {
                wrapper.isNull(CostCountTemp::getSource).or().isNull(CostCountTemp::getPower);
            };
            List<CostCountTemp> equipmentCheckList = iCostCountTempService.list(new LambdaQueryWrapper<CostCountTemp>()
                    .select(CostCountTemp::getEquipmentCode,CostCountTemp::getEquipmentName)
                    .isNotNull(CostCountTemp::getEquipmentCode).and(lambdaQueryWrapperConsumer)
                    .groupBy(CostCountTemp::getEquipmentCode,CostCountTemp::getEquipmentName));
            if(equipmentCheckList.size() > 0){
                for (CostCountTemp costCountTemp : equipmentCheckList) {
                    sb.append("设备："+costCountTemp.getEquipmentCode()+(costCountTemp.getEquipmentName()==null?"在设备档案中不存在，请联系MES同步设备档案。<br/>":"没设置来源或者额定功率，请前往【菜单】成本模块->设备档案，维护数据<br/>"));
                }
            }
            //检查设备使用率
            List<CostCountTemp> equipmentUseageCheckList = iCostCountTempService.list(new LambdaQueryWrapper<CostCountTemp>()
                    .select(CostCountTemp::getEquipmentCode,CostCountTemp::getEquipmentName)
                    .isNull(CostCountTemp::getUsageRate).isNotNull(CostCountTemp::getEquipmentCode)
                    .groupBy(CostCountTemp::getEquipmentCode,CostCountTemp::getEquipmentName));
            if(equipmentUseageCheckList.size() > 0){
                for (CostCountTemp costCountTemp : equipmentUseageCheckList) {
                    sb.append("设备："+costCountTemp.getEquipmentCode()+"没设置使用率，请前往【菜单】成本模块->成本计算数据->设备使用率，维护数据<br/>");
                }
            }
            if(StringUtils.isNotEmpty(sb.toString())){
                baseCache.delete(CacheEnum.cost_count.getCode());
                return R.error(sb.toString());
            }
            iCostCountEquipmentDepreciationLeaseService.generateDepreciationAndLease(month);
        }catch (Exception e){
            e.printStackTrace();
            baseCache.delete(CacheEnum.cost_count.getCode());
            return R.error();
        }
        direct_labor = new R();
        equipment_power = new R();
        equipment_depreciation = new R();
        equipment_lease = new R();
        indirect_equipment = new R();
        indirect_workhours = new R();
        indirect_manager = new R();
        return R.ok();
    }

    public static void main(String[] args) {
        String ss = "a,b,c,";
        System.out.println(ss.substring(0,ss.length()-1));
    }

    @RequestMapping("/count")
    @ResponseBody
    public R count(@RequestBody String count_month){
        month = count_month;
        try {
            new Thread(new direct_labor()).start();
            new Thread(new equipment_power()).start();
            new Thread(new equipment_depreciation()).start();
            new Thread(new equipment_lease()).start();
            new Thread(new indirect_equipment()).start();
            new Thread(new indirect_workhours()).start();
            new Thread(new indirect_manager()).start();
            latch.await();
            log.info("-------------子线程已经执行完毕,继续执行主线程-------------");
            iCostCountService.arrangeTempData(month);
            //进行期初结转
            List<CostProductionIndex> productionIndexList = iCostCountService.queryBalanceOrder(month);
            Map<String, List<CostProductionIndex>> groupMap = productionIndexList.stream().collect(Collectors.groupingBy(CostProductionIndex::getMonth));
            Set<Map.Entry<String, List<CostProductionIndex>>> entries = groupMap.entrySet();
            StringBuffer sql = new StringBuffer();
            sql.append("(");
            int i = 1;
            for (Map.Entry<String, List<CostProductionIndex>> entry : entries) {
                List<CostProductionIndex> values = entry.getValue();
                Set<String> orders = values.stream().map(CostProductionIndex::getWorkOrder).collect(Collectors.toSet());
                String result = "";
                for (String s : orders) {
                    result = result+"'"+s+"',";
                }
                result = result.substring(0,result.length()-1);
                sql.append("select sale_order,customer_code,customer_name,work_order,cinvcode,cinvname,process_code,process_name,concat('initail',element_code) as element_code,concat(element_name,'(期初)') as element_name,qty,sum(amount) as amount," +
                        "create_user,create_time from cost_count_production_"+entry.getKey()+" where work_order in ("+result+") group by sale_order,customer_code," +
                        "customer_name,work_order,cinvcode,cinvname,process_code,process_name,element_code,element_name,qty,create_user,create_time");
                if(i != entries.size()){
                    sql.append("union all");
                }
                i++;
            }
            sql.append(") t");
            if(entries.size() > 0){
                iCostCountService.balance(month.replace("-",""), sql.toString());
            }
            //建立随工单号期初索引表
            iCostCountService.buildIndex(month.replace("-",""));
            StringBuffer sb = new StringBuffer();
            if(direct_labor.get("msg") != null){
                sb.append(direct_labor.get("msg")+"<br/>");
            }
            if(equipment_power.get("msg") != null){
                sb.append(equipment_power.get("msg")+"<br/>");
            }
            if(equipment_depreciation.get("msg") != null){
                sb.append(equipment_depreciation.get("msg")+"<br/>");
            }
            if(equipment_lease.get("msg") != null){
                sb.append(equipment_lease.get("msg")+"<br/>");
            }
            if(indirect_equipment.get("msg") != null){
                sb.append(indirect_equipment.get("msg")+"<br/>");
            }
            if(indirect_workhours.get("msg") != null){
                sb.append(indirect_workhours.get("msg")+"<br/>");
            }
            if(indirect_manager.get("msg") != null){
                sb.append(indirect_manager.get("msg")+"<br/>");
            }
            if(StringUtils.isNotEmpty(sb.toString())){
                return R.ok(sb.toString());
            }
        }catch (Exception e){
            e.printStackTrace();
            log.error(e.getMessage());
            return R.error("计算发生异常");
        }finally {
            baseCache.delete(CacheEnum.cost_count.getCode());
            latch = new CountDownLatch(6);
        }
        return R.ok();
    }

    /**
     * 直接人工
     */
    class direct_labor implements Runnable {
        @Override
        public void run() {
            //完工集合
            List<CostCountCompleted> completedList = new ArrayList<>();
            //在产集合
            List<CostCountProduction> productionList = new ArrayList<>();
            try {
                List<CostElementsPrice> priceList = iCostElementsService.directLaborInfo(month);
                if(priceList.size() < 1){
                    direct_labor.put("msg","获取按直接人工法计算的要素总价格数据为空，请确认本月是否有该费用产生");
                    return;
                }
                for (CostElementsPrice elementsPrice : priceList) {
                    CountEnum[] enums = CountEnum.values();
                    for (CountEnum anEnum : enums) {
                        if(elementsPrice.getCode().equals(anEnum.getConstract())){
                            List<CostCountTemp> directLaborList = iCostCountTempService.countDirectLabor(anEnum.getCode());
                            //当前班组总工时
                            BigDecimal sumWorkingHours = directLaborList.stream().map(CostCountTemp::getWorkingHours).reduce(BigDecimal.ZERO, BigDecimal::add);
                            //总金额/总工时=工时单价
                            BigDecimal price = elementsPrice.getAmount().divide(sumWorkingHours, 8, BigDecimal.ROUND_HALF_UP);
                            for (CostCountTemp costCountTemp : directLaborList) {
                                if(costCountTemp.getStatus().equals("完工")){
                                    CostCountCompleted completed = CostCountCompleted.instance(costCountTemp);
                                    completed.setElementCode(elementsPrice.getCode());
                                    completed.setElementName(elementsPrice.getName());
                                    completed.setAmount(costCountTemp.getWorkingHours().multiply(price));
                                    completedList.add(completed);
                                }else{
                                    CostCountProduction production = CostCountProduction.instance(costCountTemp);
                                    production.setElementCode(elementsPrice.getCode());
                                    production.setElementName(elementsPrice.getName());
                                    production.setAmount(costCountTemp.getWorkingHours().multiply(price));
                                    productionList.add(production);
                                }
                            }
                            break;
                        }
                    }
                }
                iCostCountService.completeSave(completedList, productionList);
            }catch (Exception e){
                e.printStackTrace();
                direct_labor.put("msg","直接人工计算过程中发生异常。");
            }finally {
                completedList.clear();
                productionList.clear();
                latch.countDown();
            }
        }
    }

    /**
     * 按设备功率计算（电费）
     */
    class equipment_power implements Runnable {
        @Override
        public void run() {
            //完工集合
            List<CostCountCompleted> completedList = new ArrayList<>();
            //在产集合
            List<CostCountProduction> productionList = new ArrayList<>();
            try {
                List<CostElementsPrice> priceList = iCostElementsService.equipmentPowerInfo(month);
                if(priceList.size() < 1){
                    equipment_power.put("msg","获取按设备功率法计算的要素总价格数据为空，请确认本月是否有该费用产生");
                    return;
                }
                List<CostCountTemp> list = iCostCountTempService.list(new LambdaQueryWrapper<CostCountTemp>().isNotNull(CostCountTemp::getEquipmentCode));
                //所有设备的总功率和
                BigDecimal totalPower = list.stream().map(CostCountTemp::getPower).reduce(BigDecimal.ZERO, BigDecimal::add);
                for (CostElementsPrice elementsPrice : priceList) {
                    //总金额/功率总和=功率单价
                    BigDecimal price = elementsPrice.getAmount().divide(totalPower, 8, BigDecimal.ROUND_HALF_UP);
                    for (CostCountTemp costCountTemp : list) {
                        if(costCountTemp.getStatus().equals("完工")){
                            CostCountCompleted completed = CostCountCompleted.instance(costCountTemp);
                            completed.setElementCode(elementsPrice.getCode());
                            completed.setElementName(elementsPrice.getName());
                            completed.setAmount(costCountTemp.getPower().multiply(price));
                            completedList.add(completed);
                        }else{
                            CostCountProduction production = CostCountProduction.instance(costCountTemp);
                            production.setElementCode(elementsPrice.getCode());
                            production.setElementName(elementsPrice.getName());
                            production.setAmount(costCountTemp.getPower().multiply(price));
                            productionList.add(production);
                        }
                    }
                }
                iCostCountService.completeSave(completedList, productionList);
            }catch (Exception e){
                e.printStackTrace();
                equipment_power.put("msg","设备功率法计算过程中发生异常。");
            }finally {
                completedList.clear();
                productionList.clear();
                latch.countDown();
            }
        }
    }

    /**
     * 设备折旧法
     */
    class equipment_depreciation implements Runnable {
        @Override
        public void run() {
            //完工集合
            List<CostCountCompleted> completedList = new ArrayList<>();
            //在产集合
            List<CostCountProduction> productionList = new ArrayList<>();
            try {
                /**
                 * 设备折旧直接费用
                 */
                //计算月份，用于生产并且使用率不为空或者0的设备
                List<CostCountEquipmentDepreciationLease> list = iCostCountEquipmentDepreciationLeaseService.list(new LambdaQueryWrapper<CostCountEquipmentDepreciationLease>()
                        .eq(CostCountEquipmentDepreciationLease::getMonth, month)
                        .gt(CostCountEquipmentDepreciationLease::getDirectAmount, 0)
                        .eq(CostCountEquipmentDepreciationLease::getUseProduction, true)
                        .eq(CostCountEquipmentDepreciationLease::getSource, "自购"));
                for (CostCountEquipmentDepreciationLease equipmentDepreciationLease : list) {
                    List<CostCountTemp> countTempList = iCostCountTempService.list(new LambdaQueryWrapper<CostCountTemp>()
                            .eq(CostCountTemp::getEquipmentCode, equipmentDepreciationLease.getEquipmentCode()));
                    //设备总工时
                    BigDecimal totalWorkHours = countTempList.stream().map(CostCountTemp::getWorkingHours).reduce(BigDecimal.ZERO, BigDecimal::add);
                    //平均工时费用
                    BigDecimal price = equipmentDepreciationLease.getDirectAmount().divide(totalWorkHours, 8, BigDecimal.ROUND_HALF_UP);
                    for (CostCountTemp costCountTemp : countTempList) {
                        if(costCountTemp.getStatus().equals("完工")){
                            CostCountCompleted completed = CostCountCompleted.instance(costCountTemp);
//                            completed.setElementCode(equipmentDepreciationLease.getSource().equals("自购")?CountEnum.direct_depreciation.getCode():CountEnum.direct_lease.getCode());
//                            completed.setElementName(equipmentDepreciationLease.getSource().equals("自购")?CountEnum.direct_depreciation.getDescribe():CountEnum.direct_lease.getDescribe());
                            completed.setElementCode(CountEnum.direct_depreciation.getCode());
                            completed.setElementName(CountEnum.direct_depreciation.getDescribe());
                            completed.setAmount(costCountTemp.getWorkingHours().multiply(price));
                            completedList.add(completed);
                        }else{
                            CostCountProduction production = CostCountProduction.instance(costCountTemp);
                            production.setElementCode(CountEnum.direct_depreciation.getCode());
                            production.setElementName(CountEnum.direct_depreciation.getDescribe());
                            production.setAmount(costCountTemp.getWorkingHours().multiply(price));
                            productionList.add(production);
                        }
                    }
                }
                /**
                 * 设备折旧间接费用
                 */
                //计算月份，未用于生产的设备
//                List<CostCountEquipmentDepreciationLease> onUseList = iCostCountEquipmentDepreciationLeaseService.list(new LambdaQueryWrapper<CostCountEquipmentDepreciationLease>()
//                        .eq(CostCountEquipmentDepreciationLease::getMonth, month)
//                        .eq(CostCountEquipmentDepreciationLease::getUseProduction, false));
                //未参与生产的金额总和
//                BigDecimal totalNoUseAmount = onUseList.stream().map(obj -> obj.getAmount()).reduce(BigDecimal.ZERO, BigDecimal::add);
                //计算月份，使用率不为100%的设备
                List<CostCountEquipmentDepreciationLease> ortherList = iCostCountEquipmentDepreciationLeaseService.list(new LambdaQueryWrapper<CostCountEquipmentDepreciationLease>()
                        .eq(CostCountEquipmentDepreciationLease::getMonth, month)
                        .gt(CostCountEquipmentDepreciationLease::getIndirectAmount, 0)
                        .eq(CostCountEquipmentDepreciationLease::getSource, "自购"));
//                list.addAll(ortherList);
                //使用率不为100%设备的金额总和
                BigDecimal totalIndirectAmount = ortherList.stream().map(obj -> obj.getIndirectAmount()).reduce(BigDecimal.ZERO, BigDecimal::add);
//                totalIndirectAmount = totalIndirectAmount.add(totalNoUseAmount);

                //所有使用到有折旧或者租赁设备的工序
                List<CostCountTemp> countTempList = iCostCountTempService.listHasDepreciationOrLease(month, "自购");
                //工时*折旧、租赁额
                BigDecimal denominatorSum = countTempList.stream().map(obj -> obj.getWorkingHours().multiply(obj.getAmount())).reduce(BigDecimal.ZERO, BigDecimal::add);
                //间接费用总和/工时*折旧、租赁额总和
                BigDecimal price = totalIndirectAmount.divide(denominatorSum, 8, BigDecimal.ROUND_HALF_UP);
                for (CostCountTemp costCountTemp : countTempList) {
                    if(costCountTemp.getStatus().equals("完工")){
                        CostCountCompleted completed = CostCountCompleted.instance(costCountTemp);
                        completed.setElementCode(CountEnum.indirect_depreciation.getCode());
                        completed.setElementName(CountEnum.indirect_depreciation.getDescribe());
                        completed.setAmount(costCountTemp.getWorkingHours().multiply(price).multiply(costCountTemp.getAmount()));
                        completedList.add(completed);
                    }else{
                        CostCountProduction production = CostCountProduction.instance(costCountTemp);
                        production.setElementCode(CountEnum.indirect_depreciation.getCode());
                        production.setElementName(CountEnum.indirect_depreciation.getDescribe());
                        production.setAmount(costCountTemp.getWorkingHours().multiply(price).multiply(costCountTemp.getAmount()));
                        productionList.add(production);
                    }
                }
                iCostCountService.completeSave(completedList, productionList);
            }catch (Exception e){
                e.printStackTrace();
                equipment_depreciation.put("msg","设备折旧计算过程中发生异常。");
            }finally {
                completedList.clear();
                productionList.clear();
                latch.countDown();
            }
        }
    }

    /**
     * 设备租赁法
     */
    class equipment_lease implements Runnable {
        @Override
        public void run() {
            //完工集合
            List<CostCountCompleted> completedList = new ArrayList<>();
            //在产集合
            List<CostCountProduction> productionList = new ArrayList<>();
            try {
                /**
                 * 设备租赁直接费用
                 */
                //计算月份，用于生产并且使用率不为空或者0的设备
                List<CostCountEquipmentDepreciationLease> list = iCostCountEquipmentDepreciationLeaseService.list(new LambdaQueryWrapper<CostCountEquipmentDepreciationLease>()
                        .eq(CostCountEquipmentDepreciationLease::getMonth, month)
                        .gt(CostCountEquipmentDepreciationLease::getDirectAmount, 0)
                        .eq(CostCountEquipmentDepreciationLease::getUseProduction, true)
                        .eq(CostCountEquipmentDepreciationLease::getSource, "租赁"));
                for (CostCountEquipmentDepreciationLease equipmentDepreciationLease : list) {
                    List<CostCountTemp> countTempList = iCostCountTempService.list(new LambdaQueryWrapper<CostCountTemp>()
                            .eq(CostCountTemp::getEquipmentCode, equipmentDepreciationLease.getEquipmentCode()));
                    //设备总工时
                    BigDecimal totalWorkHours = countTempList.stream().map(CostCountTemp::getWorkingHours).reduce(BigDecimal.ZERO, BigDecimal::add);
                    //平均工时费用
                    BigDecimal price = equipmentDepreciationLease.getDirectAmount().divide(totalWorkHours, 8, BigDecimal.ROUND_HALF_UP);
                    for (CostCountTemp costCountTemp : countTempList) {
                        if(costCountTemp.getStatus().equals("完工")){
                            CostCountCompleted completed = CostCountCompleted.instance(costCountTemp);
                            completed.setElementCode(CountEnum.direct_lease.getCode());
                            completed.setElementName(CountEnum.direct_lease.getDescribe());
                            completed.setAmount(costCountTemp.getWorkingHours().multiply(price));
                            completedList.add(completed);
                        }else{
                            CostCountProduction production = CostCountProduction.instance(costCountTemp);
                            production.setElementCode(CountEnum.direct_lease.getCode());
                            production.setElementName(CountEnum.direct_lease.getDescribe());
                            production.setAmount(costCountTemp.getWorkingHours().multiply(price));
                            productionList.add(production);
                        }
                    }
                }
                /**
                 * 设备租赁间接费用
                 */
                //计算月份，未用于生产的设备
//                List<CostCountEquipmentDepreciationLease> onUseList = iCostCountEquipmentDepreciationLeaseService.list(new LambdaQueryWrapper<CostCountEquipmentDepreciationLease>()
//                        .eq(CostCountEquipmentDepreciationLease::getMonth, month)
//                        .eq(CostCountEquipmentDepreciationLease::getUseProduction, false));
                //未参与生产的金额总和
//                BigDecimal totalNoUseAmount = onUseList.stream().map(obj -> obj.getAmount()).reduce(BigDecimal.ZERO, BigDecimal::add);
                //计算月份，使用率不为100%的设备
                List<CostCountEquipmentDepreciationLease> ortherList = iCostCountEquipmentDepreciationLeaseService.list(new LambdaQueryWrapper<CostCountEquipmentDepreciationLease>()
                        .eq(CostCountEquipmentDepreciationLease::getMonth, month)
                        .gt(CostCountEquipmentDepreciationLease::getIndirectAmount, 0)
                        .eq(CostCountEquipmentDepreciationLease::getSource, "租赁"));
//                list.addAll(ortherList);
                //使用率不为100%设备的金额总和
                BigDecimal totalIndirectAmount = ortherList.stream().map(obj -> obj.getIndirectAmount()).reduce(BigDecimal.ZERO, BigDecimal::add);
//                totalIndirectAmount = totalIndirectAmount.add(totalNoUseAmount);

                //所有使用到有折旧或者租赁设备的工序
                List<CostCountTemp> countTempList = iCostCountTempService.listHasDepreciationOrLease(month, "租赁");
                //工时*折旧、租赁额
                BigDecimal denominatorSum = countTempList.stream().map(obj -> obj.getWorkingHours().multiply(obj.getAmount())).reduce(BigDecimal.ZERO, BigDecimal::add);
                //间接费用总和/工时*折旧、租赁额总和
                BigDecimal price = totalIndirectAmount.divide(denominatorSum, 8, BigDecimal.ROUND_HALF_UP);
                for (CostCountTemp costCountTemp : countTempList) {
                    if(costCountTemp.getStatus().equals("完工")){
                        CostCountCompleted completed = CostCountCompleted.instance(costCountTemp);
                        completed.setElementCode(CountEnum.indirect_lease.getCode());
                        completed.setElementName(CountEnum.indirect_lease.getDescribe());
                        completed.setAmount(costCountTemp.getWorkingHours().multiply(price).multiply(costCountTemp.getAmount()));
                        completedList.add(completed);
                    }else{
                        CostCountProduction production = CostCountProduction.instance(costCountTemp);
                        production.setElementCode(CountEnum.indirect_lease.getCode());
                        production.setElementName(CountEnum.indirect_lease.getDescribe());
                        production.setAmount(costCountTemp.getWorkingHours().multiply(price).multiply(costCountTemp.getAmount()));
                        productionList.add(production);
                    }
                }
                iCostCountService.completeSave(completedList, productionList);
            }catch (Exception e){
                e.printStackTrace();
                equipment_lease.put("msg","设备租赁计算过程中发生异常。");
            }finally {
                completedList.clear();
                productionList.clear();
                latch.countDown();
            }
        }
    }

    /**
     *间接费用-设备价值法
     */
    class indirect_equipment implements Runnable{
        @Override
        public void run() {
            //完工集合
            List<CostCountCompleted> completedList = new ArrayList<>();
            //在产集合
            List<CostCountProduction> productionList = new ArrayList<>();
            try {
                List<CostElementsPrice> priceList = iCostElementsService.indirectEquipmentInfo(month);
                if(priceList.size() < 1){
                    indirect_equipment.put("msg","获取按间接费用-设备价值法计算的要素总价格数据为空，请确认本月是否有该费用产生");
                    return;
                }
                //所有使用到有折旧或者租赁设备的工序
                List<CostCountTemp> countTempList = iCostCountTempService.listHasDepreciationOrLease(month, month);
                //工时*折旧、租赁额
                BigDecimal denominatorSum = countTempList.stream().map(obj -> obj.getWorkingHours().multiply(obj.getAmount())).reduce(BigDecimal.ZERO, BigDecimal::add);
                //间接费用总和/工时*折旧、租赁额总和
                for (CostElementsPrice elementsPrice : priceList) {
                    //间接费用总和/工时*折旧、租赁额总和
                    BigDecimal price = elementsPrice.getAmount().divide(denominatorSum, 8, BigDecimal.ROUND_HALF_UP);
                    for (CostCountTemp costCountTemp : countTempList) {
                        if(costCountTemp.getStatus().equals("完工")){
                            CostCountCompleted completed = CostCountCompleted.instance(costCountTemp);
                            completed.setElementCode(elementsPrice.getCode());
                            completed.setElementName(elementsPrice.getName());
                            completed.setAmount(costCountTemp.getWorkingHours().multiply(price).multiply(costCountTemp.getAmount()));
                            completedList.add(completed);
                        }else{
                            CostCountProduction production = CostCountProduction.instance(costCountTemp);
                            production.setElementCode(elementsPrice.getCode());
                            production.setElementName(elementsPrice.getName());
                            production.setAmount(costCountTemp.getWorkingHours().multiply(price).multiply(costCountTemp.getAmount()));
                            productionList.add(production);
                        }
                    }
                }
                iCostCountService.completeSave(completedList, productionList);
            }catch (Exception e){
                e.printStackTrace();
                indirect_equipment.put("msg","间接费用-设备价值法计算过程中发生异常。");
            }finally {
                completedList.clear();
                productionList.clear();
                latch.countDown();
            }
        }
    }

    /**
     *间接费用-实际工时法
     */
    class indirect_workhours implements Runnable{
        @Override
        public void run() {
            //完工集合
            List<CostCountCompleted> completedList = new ArrayList<>();
            //在产集合
            List<CostCountProduction> productionList = new ArrayList<>();
            try {
                List<CostElementsPrice> priceList = iCostElementsService.indirectWorkhoursInfo(month);
                if(priceList.size() < 1){
                    indirect_workhours.put("msg","获取按间接费用-实际工时法计算的要素总价格数据为空，请确认本月是否有该费用产生");
                }
                //所有生产数据
                List<CostCountTemp> countTempList = iCostCountTempService.list(new LambdaQueryWrapper<CostCountTemp>()
                        .select(CostCountTemp::getSaleOrder,CostCountTemp::getCustomerCode,CostCountTemp::getCustomerName,CostCountTemp::getWorkOrder,CostCountTemp::getCinvcode,CostCountTemp::getCinvname,CostCountTemp::getProcessCode,CostCountTemp::getProcessName,CostCountTemp::getQty,CostCountTemp::getWorkingHours,CostCountTemp::getStatus)
                        .groupBy(CostCountTemp::getSaleOrder,CostCountTemp::getCustomerCode,CostCountTemp::getCustomerName,CostCountTemp::getWorkOrder,CostCountTemp::getCinvcode,CostCountTemp::getCinvname,CostCountTemp::getProcessCode,CostCountTemp::getProcessName,CostCountTemp::getQty,CostCountTemp::getWorkingHours,CostCountTemp::getStatus));
                //总工时
                BigDecimal workhoursSum = countTempList.stream().map(CostCountTemp::getWorkingHours).reduce(BigDecimal.ZERO, BigDecimal::add);
                for (CostElementsPrice elementsPrice : priceList) {
                    //间接费用总和/总工时
                    BigDecimal price = elementsPrice.getAmount().divide(workhoursSum, 8, BigDecimal.ROUND_HALF_UP);
                    for (CostCountTemp costCountTemp : countTempList) {
                        if(costCountTemp.getStatus().equals("完工")){
                            CostCountCompleted completed = CostCountCompleted.instance(costCountTemp);
                            completed.setElementCode(elementsPrice.getCode());
                            completed.setElementName(elementsPrice.getName());
                            completed.setAmount(costCountTemp.getWorkingHours().multiply(price));
                            completedList.add(completed);
                        }else{
                            CostCountProduction production = CostCountProduction.instance(costCountTemp);
                            production.setElementCode(elementsPrice.getCode());
                            production.setElementName(elementsPrice.getName());
                            production.setAmount(costCountTemp.getWorkingHours().multiply(price));
                            productionList.add(production);
                        }
                    }
                }
                iCostCountService.completeSave(completedList, productionList);
            }catch (Exception e){
                e.printStackTrace();
                indirect_workhours.put("msg","间接费用-实际工时法计算过程中发生异常。");
            }finally {
                completedList.clear();
                productionList.clear();
                latch.countDown();
            }
        }
    }

    /**
     *间接费用-管理权重法
     */
    class indirect_manager implements Runnable{
        @Override
        public void run() {
            //完工集合
            List<CostCountCompleted> completedList = new ArrayList<>();
            //在产集合
            List<CostCountProduction> productionList = new ArrayList<>();
            try {
                List<CostElementsPrice> priceList = iCostElementsService.indirectManagerInfo(month);
                if(priceList.size() < 1){
                    indirect_manager.put("msg","获取按间接费用-管理权重法计算的要素总价格数据为空，请确认本月是否有该费用产生");
                }
                //所有生产数据
                List<CostCountTemp> countTempList = iCostCountTempService.list(new LambdaQueryWrapper<CostCountTemp>()
                        .select(CostCountTemp::getSaleOrder,CostCountTemp::getCustomerCode,CostCountTemp::getCustomerName,CostCountTemp::getWorkOrder,CostCountTemp::getCinvcode,CostCountTemp::getCinvname,CostCountTemp::getProcessCode,CostCountTemp::getProcessName,CostCountTemp::getQty,CostCountTemp::getWorkingHours,CostCountTemp::getManagerScale,CostCountTemp::getStatus)
                        .groupBy(CostCountTemp::getSaleOrder,CostCountTemp::getCustomerCode,CostCountTemp::getCustomerName,CostCountTemp::getWorkOrder,CostCountTemp::getCinvcode,CostCountTemp::getCinvname,CostCountTemp::getProcessCode,CostCountTemp::getProcessName,CostCountTemp::getQty,CostCountTemp::getWorkingHours,CostCountTemp::getManagerScale,CostCountTemp::getStatus));
                //工序加工数量*工序管理属性占比
                BigDecimal qtyAndManagerSum = countTempList.stream().map(obj -> obj.getQty().multiply(obj.getManagerScale())).reduce(BigDecimal.ZERO, BigDecimal::add);
                for (CostElementsPrice elementsPrice : priceList) {
                    //间接费用总和/工序加工数量*工序管理属性占比
                    BigDecimal price = elementsPrice.getAmount().divide(qtyAndManagerSum, 8, BigDecimal.ROUND_HALF_UP);
                    for (CostCountTemp costCountTemp : countTempList) {
                        if(costCountTemp.getStatus().equals("完工")){
                            CostCountCompleted completed = CostCountCompleted.instance(costCountTemp);
                            completed.setElementCode(elementsPrice.getCode());
                            completed.setElementName(elementsPrice.getName());
                            completed.setAmount(costCountTemp.getQty().multiply(costCountTemp.getManagerScale()).multiply(price));
                            completedList.add(completed);
                        }else{
                            CostCountProduction production = CostCountProduction.instance(costCountTemp);
                            production.setElementCode(elementsPrice.getCode());
                            production.setElementName(elementsPrice.getName());
                            production.setAmount(costCountTemp.getQty().multiply(costCountTemp.getManagerScale()).multiply(price));
                            productionList.add(production);
                        }
                    }
                }
                iCostCountService.completeSave(completedList, productionList);
            }catch (Exception e){
                e.printStackTrace();
                indirect_manager.put("msg","间接费用-管理权重法计算过程中发生异常。");
            }finally {
                completedList.clear();
                productionList.clear();
                latch.countDown();
            }
        }
    }
}

